/*****************************************************************************\
 *             University of Illinois/NCSA Open Source License
 *
 * 
 *      Copyright © 2012,2013, The Board of Trustees of the University of Illinois. All rights reserved.
 *
 *      Developed by: Rakesh Bobba, Derek Dagit, Erich Heine, Denis Kholine,
 *                    Klara Nahrstedt, David Rodgers,   William H. Sanders, Tim Yardley
 *
 *      Information Trust Institute/Coordinated Science Laboratory
 * 
 *      University of Illinois
 *      
 *      The Board of Trustees of the University of Illinois
 *      109 Coble Hall
 *      801 South Wright Street
 *      Champaign, IL 61820-6242
 *
 *      http://www.iti.illinois.edu / http://csl.illinois.edu
 * 
 *      Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
 *      associated documentation files (the “Software”), to deal with the Software without restriction, 
 *      including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *      and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
 *      subject to the following conditions:
 *
 *      Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *      following disclaimers.
 *      
 *      Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
 *      the following disclaimers in the documentation and/or other materials provided with the distribution.
 *
 *      Neither the names of Information Trust institute, Coordinated Science Laboratory, University of Illinois,
 *      The Board of Trustees of the University of Illinois nor the names of its contributors may be used to 
 *      endorse or promote products derived from this Software without specific prior written permission.
 *      
 *      THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 *      LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN
 *      NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 *      WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 *      SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE.
 *      
 \*****************************************************************************/

﻿using System;
using System.Collections.Generic;
 using Disruptor;
 using SIEGate.Core.Adapters;

namespace SIEGate.Core.MessageBusses
{
    public class RingBufferMessageBus : IMessageBus
    {
        private List<Sequence> _gates = new List<Sequence>(1024);
        private RingBuffer<Routable> _ringBuff;
        private List<RingBufferMessageBusProxy> m_proxies;

        private Dictionary<Sequence, string> _gatemap = new Dictionary<Sequence, string>();

        public RingBufferMessageBus(int buffsize = 2<<16)
        {
            _ringBuff = new RingBuffer<Routable>(() => new Routable(),
                new MultiThreadedClaimStrategy(buffsize),
                new SleepingWaitStrategy());
        }

        internal RingBuffer<Routable> RingBuffer { 
            get { return _ringBuff; }
        }

        internal RingBufferMessageBusProducer GetProducer(ISet<Guid> streamIDs, QOSParams qos)
        {
            return new RingBufferMessageBusProducer(streamIDs, qos, _ringBuff);
        }

        internal RingBufferMessageBusConsumer GetConsumer(ISet<Guid> streamIDs)
        {
            long startat = _ringBuff.Cursor;
            // Everyone gets thier own barrier. This gives us a way to interrupt each consumer independently via
            // barrier.Alert() (via the consumer object)
            ISequenceBarrier consumerBarrier = _ringBuff.NewBarrier();
            RingBufferMessageBusConsumer res = new RingBufferMessageBusConsumer(streamIDs, this, consumerBarrier, _ringBuff.Cursor);
            return res;
        }
        public IMessageBusProxy GetProxy(string name)
        {
            RingBufferMessageBusProxy res = new RingBufferMessageBusProxy(this);
            m_proxies.Add(res);
            _gatemap.Add(res.Consumer.Sequence, name);
            return res;
        }

        internal void StartConsumer(RingBufferMessageBusConsumer toStart)
        {
            _gates.Add(toStart.Sequence);
            _ringBuff.SetGatingSequences(_gates.ToArray());

        }

        internal void PauseConsumer(RingBufferMessageBusConsumer toPause)
        {
            _gates.Remove(toPause.Sequence);
            _ringBuff.SetGatingSequences(_gates.ToArray());
        }

        public void EnablePath(Guid messageId, OutputAdapter adapter)
        {
            throw new NotImplementedException();
        }

        public void DisablePath(Guid messageId, OutputAdapter adapter)
        {
            throw new NotImplementedException();
        }
        public void Stats()
        {
            Console.WriteLine("Stats for ringbuffer:");
            Console.WriteLine("\tcurrent cursor:\t{0}", _ringBuff.Cursor);
            foreach (Sequence s in _gates)
            {
                Console.WriteLine("\tgval for {0}:\t{1}", _gatemap[s], s.Value);
            }
        }
    }
}
